package BaseObject;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Vector;

public class Motor {

	static Properties prop;

	public static Vector<Taxi> taxis = new Vector<Taxi>();
	public static Vector<Client> clients = new Vector<Client>();
	public static Vector<Client> clientsTaken = new Vector<Client>();

	public static int cityRay;
	public static long timeNextCustomer = 0;
	public static double currentTime=0.0;
	public static double stepTime;
	public static double lambda;

	public static int nbTaxis;
	public static int mode;
	public static int temps;
	public static int nbClient;

	public static int MODE_CLIENT = 0;
	public static int MODE_TEMPS = 1;

	private int nbClientProduce=0;
	private int nbClientMissed=0;
	private static int nbClientDone=0;
	
	public Motor(){
		this.initialize();
	}
	
	/*constructor used only for testing the simulationInterface*/
	public Motor(Taxi taxi,	ArrayList<Client> clientList){
		taxis.add(taxi);
		clients.addAll(clientList);
	}

	public Properties loadProperties(String propertiesFileLocation) {
		Properties props = new Properties();
		try {
			props.load(new FileInputStream(propertiesFileLocation));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return props;
	}

	public void initialize(){
		currentTime = 0.0;
		timeNextCustomer = 0;

		//Read in a configuration file
		prop = loadProperties("src/variables.properties");

		cityRay = Integer.parseInt(prop.getProperty("rayCircle"));
		stepTime= Double.parseDouble(prop.getProperty("stepTime"));
		lambda= Double.parseDouble(prop.getProperty("lambda"));
		nbTaxis = Integer.parseInt(prop.getProperty("nbTaxis"));
		mode = Integer.parseInt(prop.getProperty("mode"));
		temps = Integer.parseInt(prop.getProperty("temps"));
		nbClient = Integer.parseInt(prop.getProperty("nbClient"));

		Client.maxDeviationThreeshold = Double.parseDouble(prop.getProperty("maxDeviationThreeshold"));
		Client.mu = Double.parseDouble(prop.getProperty("mu"));
		Client.sigma = Double.parseDouble(prop.getProperty("sigma"));
		Taxi.comparator = Integer.parseInt(prop.getProperty("comparator"));
	}

	public void updateTaxis() {
		System.out.println("entering in update Taxi");
		for(Taxi t : taxis ){
			t.calculItinerary();
			t.move();
		}
		System.out.println("exiting update Taxi");
	}

	public static Vector<Taxi> getTaxis() {
		return taxis;
	}

	public static void setTaxis(Vector<Taxi> taxis) {
		Motor.taxis = taxis;
	}

	public static Vector<Client> getClients() {
		return clients;
	}

	public static void setClients(Vector<Client> clients) {
		Motor.clients = clients;
	}

	public static int getCityRay() {
		return cityRay;
	}

	public static void setCityRay(int cityRay) {
		Motor.cityRay = cityRay;
	}

	public long getTimeNextCustomer() {
		return timeNextCustomer;
	}

	public void setTimeNextCustomer(long timeNextCustomer) {
		Motor.timeNextCustomer = timeNextCustomer;
	}

	public static double getCurrentTime() {
		return currentTime;
	}

	public static void setCurrentTime(double currentTime) {
		Motor.currentTime = currentTime;
	}

	public static double getStepTime() {
		return stepTime;
	}

	public static void setStepTime(double stepTime) {
		Motor.stepTime = stepTime;
	}

	public void updateClients() {
		System.out.println("entering in update Client");

		Vector<Client> c2 = new Vector<Client>();
		for( Client c : clients){
			if(c.keepWaiting())
				c2.add(c);
			else {
				System.out.println("Un client disparait");
				nbClientMissed++;
			}
		}
		clients=c2;

		//Check out whether we have to had a new customer
		if(currentTime > timeNextCustomer ){
			if(mode == MODE_CLIENT && nbClient <= nbClientProduce)
				return;
			System.out.println("Adding a new client");
			//Add a new client
			Client c = new Client();

			clients.add(c);
			nbClientProduce++;

			//Update next customer's appearing time
			double d=Tools.Exp(lambda);
			double l =d * 1000.0;
			System.out.println("Next client in ; " + String.valueOf(l));
			timeNextCustomer = (long) (currentTime + (int)l );
			System.out.println("Next client in : " + String.valueOf(timeNextCustomer));
		}

		System.out.println("Next client : " + String.valueOf(timeNextCustomer) + " - CURRENT time : " + String.valueOf(currentTime));
		System.out.println("exiting in update Taxi");
	}

	public boolean StopTheSystem(){
		boolean stop = false;

		if(mode == MODE_CLIENT ){
			if(nbClient <= nbClientProduce && clients.size()==0 && clientsTaken.size()==0)
				return true;
		}
		else if(mode == MODE_TEMPS){
			if(currentTime >= temps && clients.size()==0 && clientsTaken.size()==0)
				return true;
		}
		return stop;
	}


	
	public void increaseCurrentTime(){
		currentTime += stepTime;
	}
	public static void increaseNbClientDone(){
		nbClientDone++;
	}
	public int getNbClientProduced(){return nbClientProduce;}
	public int getNbClientDone(){return nbClientDone;}
	public int getNbClientMissed(){	return nbClientMissed;}

}
